import { GUI } from "dat.gui"
import { 
  AxesHelper,
  BackSide,
  Float32BufferAttribute,
  HemisphereLight,
  Mesh,
  MeshNormalMaterial,
  PerspectiveCamera, 
  QuadraticBezierCurve3, 
  Scene, 
  TorusKnotGeometry, 
  TubeBufferGeometry, 
  Vector2, 
  Vector3, 
  WebGLRenderer,
  Group,
  BoxGeometry,
  VertexColors,
  SphereGeometry,
  ArrowHelper,
  Geometry
} from "three"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import stats from '../utils/stats'

const scene = new Scene()
const camera = new PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
// 不能设置为0
camera.position.set(-3, 13, 39)

const renderer = new WebGLRenderer({ antialias: true })
renderer.setPixelRatio(window.devicePixelRatio)
renderer.setClearColor(0xeeeeee)
renderer.setSize(window.innerWidth, window.innerHeight)

document.body.appendChild(renderer.domElement)

new OrbitControls(camera, renderer.domElement)

// 添加坐标系
const axes = new AxesHelper(100)
scene.add(axes)

const light = new HemisphereLight(0xffffff, 0xcccccc, 1)
scene.add(light)

const material = new MeshNormalMaterial({
  transparent: true,
  opacity: 0.5
})

let group: Group
const controls = {
  numberOfObjects: 500,
  combined: false,

  draw() {
    let toRemove: Mesh[] = [];
    scene.traverse(e => {
      if (e instanceof Mesh) toRemove.push(e);
    });
    toRemove.forEach(e => {
      scene.remove(e)
    });

    if (this.combined) {
      let geometry = new Geometry();

      for (let i = 0; i < controls.numberOfObjects; i++) {
        let cubeMesh = addCube();
        cubeMesh.updateMatrix();
        // 创建联合体，提高渲染性能
        geometry.merge(cubeMesh.geometry, cubeMesh.matrix);
      }
      scene.add(new Mesh(geometry, material))
    } else {
      for (let i = 0; i < controls.numberOfObjects; i++) {
        scene.add(addCube());
      }
    }
  }
}

controls.draw()

function addCube(): Mesh<Geometry> {
  let cubeSize = 1.0;
  let geometry = new BoxGeometry(cubeSize, cubeSize, cubeSize);

  let cube = new Mesh(geometry, material);
  cube.position.x = -60 + Math.round(Math.random() * 100);
  cube.position.y = Math.round(Math.random() * 10);
  cube.position.z = -150 + Math.round(Math.random() * 175);

  return cube;
}

const gui = new GUI()
gui.add(controls, 'combined').name('合并渲染').onChange(controls.draw.bind(controls))
gui.add(controls, 'numberOfObjects', 0, 20000, 1).name('数量').onChange(controls.draw.bind(controls))

function render(time: number): void {
  stats.update()

  requestAnimationFrame(render)
  renderer.render(scene, camera)
}

requestAnimationFrame(render)